package com.vinjogames.gfx;

import javax.microedition.khronos.opengles.GL10;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.opengl.GLUtils;

import com.vinjogames.TankGame.R;
import com.vinjogames.util.GameConVars;
import com.vinjogames.util.Logger;

public class SpriteSheet {	
	private Bitmap mSpriteSheet;
	private Bitmap mUISheet;
	private Bitmap mBackgroundSheet;
	private BitmapFactory.Options options; 
	
	private Bitmap mFontBitmap;
	private Context mContext;
	
	private int[][] allTextures = new int[GameConVars.GRAPHIC_MAX_TEXTURES][];
	
	private SpriteSheet(){};

	private static class SpriteSheetHolder {
		public static final SpriteSheet instance = new SpriteSheet();
	}

	public static SpriteSheet getInstance(){
		return SpriteSheetHolder.instance;
	}
	
	public void setContext(Context context){ mContext = context; }
	
	public int[] getTexture(int key){
		return allTextures[key];
	}
	
	public void loadBitmaps(){
//		 options.inSampleSize =2;
		
		if(mSpriteSheet == null){
			mSpriteSheet = BitmapFactory.decodeResource(mContext.getResources(), R.drawable.lspritesheet, options);
		}
		if(mBackgroundSheet == null){
			mBackgroundSheet = BitmapFactory.decodeResource(mContext.getResources(), R.drawable.backgroundsheet,options);
		}
	}
	
	public void loadAllTextures(GL10 gl){
		loadBackgroundTextures(gl);
		
		if(mSpriteSheet == null){
			mSpriteSheet = BitmapFactory.decodeResource(mContext.getResources(), R.drawable.lspritesheet,options);
		}
		
		allTextures[GameConVars.GRAPHIC_WATER_TEXTURE] = loadTexture(gl, Bitmap.createBitmap(mSpriteSheet, 1792, 0, 256, 256), 256, 256);
		allTextures[GameConVars.GRAPHIC_GRASS_TEXTURE] = loadTexture(gl, Bitmap.createBitmap(mSpriteSheet, 1792, 256, 256, 256), 256, 256);
		allTextures[GameConVars.GRAPHIC_STONE_TEXTURE] = loadTexture(gl, Bitmap.createBitmap(mSpriteSheet, 1792, 512, 256, 256), 256, 256);
		allTextures[GameConVars.GRAPHIC_WOOD_TEXTURE]  = loadTexture(gl, Bitmap.createBitmap(mSpriteSheet, 1792, 768, 256, 256), 256, 256);
		allTextures[GameConVars.GRAPHIC_TREE]          = loadTexture(gl, Bitmap.createBitmap(mSpriteSheet, 256, 1280, 128, 128), 128, 128);
		allTextures[GameConVars.GRAPHIC_GROUND_TEXTURES[0]]  = loadTexture(gl, Bitmap.createBitmap(mSpriteSheet, 1792, 1024, 256, 256), 256, 256);
		allTextures[GameConVars.GRAPHIC_GROUND_TEXTURES[1]]  = loadTexture(gl, Bitmap.createBitmap(mSpriteSheet, 1792, 0, 256, 256), 256, 256);
		allTextures[GameConVars.GRAPHIC_GROUND_TEXTURES[2]]  = loadTexture(gl, Bitmap.createBitmap(mSpriteSheet, 1792, 256, 256, 256), 256, 256);
		allTextures[GameConVars.GRAPHIC_GROUND_TEXTURES[3]]  = loadTexture(gl, Bitmap.createBitmap(mSpriteSheet, 1792, 512, 256, 256), 256, 256);
		allTextures[GameConVars.GRAPHIC_GROUND_TEXTURES[4]]  = loadTexture(gl, Bitmap.createBitmap(mSpriteSheet, 1792, 768, 256, 256), 256, 256);
		
		allTextures[GameConVars.GRAPHIC_TANKS[0]] = loadTexture(gl, Bitmap.createBitmap(mSpriteSheet, 0, 0, 1280, 128), 128, 128);
		allTextures[GameConVars.GRAPHIC_TANKS[1]] = loadTexture(gl, Bitmap.createBitmap(mSpriteSheet, 0, 128, 1280, 128), 128, 128);
		allTextures[GameConVars.GRAPHIC_TANKS[2]] = loadTexture(gl, Bitmap.createBitmap(mSpriteSheet, 0, 256, 128, 128), 128, 128);
		allTextures[GameConVars.GRAPHIC_TANKS[3]] = loadTexture(gl, Bitmap.createBitmap(mSpriteSheet, 0, 384, 128, 128), 128, 128);
		allTextures[GameConVars.GRAPHIC_TANKS[4]] = loadTexture(gl, Bitmap.createBitmap(mSpriteSheet, 0, 512, 1280, 128), 128, 128);
		allTextures[GameConVars.GRAPHIC_TANKS[5]] = loadTexture(gl, Bitmap.createBitmap(mSpriteSheet, 0, 640, 1280, 128), 128, 128);
		allTextures[GameConVars.GRAPHIC_TANKS[6]] = loadTexture(gl, Bitmap.createBitmap(mSpriteSheet, 0, 768, 1280, 128), 128, 128);
		allTextures[GameConVars.GRAPHIC_TANKS[7]] = loadTexture(gl, Bitmap.createBitmap(mSpriteSheet, 0, 896, 128, 128), 128, 128);
		allTextures[GameConVars.GRAPHIC_TANKS[8]] = loadTexture(gl, Bitmap.createBitmap(mSpriteSheet, 0, 512, 128, 128), 128, 128);

		allTextures[GameConVars.GRAPHIC_RESOURCE]   = loadTexture(gl, Bitmap.createBitmap(mSpriteSheet, 256, 1408, 256, 128), 256, 128);

		allTextures[GameConVars.GRAPHIC_TURRETS[0]] = loadTexture(gl, Bitmap.createBitmap(mSpriteSheet, 0, 1152, 256, 256), 256, 256);
		
		allTextures[GameConVars.GRAPHIC_GUNS[0]]  = loadTexture(gl, Bitmap.createBitmap(mSpriteSheet, 0, 1024, 128, 32), 128, 32);
		allTextures[GameConVars.GRAPHIC_GUNS[1]] = loadTexture(gl, Bitmap.createBitmap(mSpriteSheet, 0, 1056, 128, 32), 128, 32);
		allTextures[GameConVars.GRAPHIC_GUNS[2]] = loadTexture(gl, Bitmap.createBitmap(mSpriteSheet, 256, 1056, 128, 32), 128, 32);
		allTextures[GameConVars.GRAPHIC_GUNS[3]] = loadTexture(gl, Bitmap.createBitmap(mSpriteSheet, 128, 1056, 128, 32), 128, 32);
		allTextures[GameConVars.GRAPHIC_GUNS[4]] = loadTexture(gl, Bitmap.createBitmap(mSpriteSheet, 256, 1024, 128, 32), 128, 32);
		allTextures[GameConVars.GRAPHIC_GUNS[5]] = loadTexture(gl, Bitmap.createBitmap(mSpriteSheet, 256, 1024, 128, 32), 128, 32);
		allTextures[GameConVars.GRAPHIC_GUNS[6]] = loadTexture(gl, Bitmap.createBitmap(mSpriteSheet, 256, 1024, 128, 32), 128, 32);
		allTextures[GameConVars.GRAPHIC_GUNS[7]] = loadTexture(gl, Bitmap.createBitmap(mSpriteSheet, 256, 1024, 128, 32), 128, 32);
		allTextures[GameConVars.GRAPHIC_GUNS[8]] = loadTexture(gl, Bitmap.createBitmap(mSpriteSheet, 128, 1024, 128, 32), 128, 32);
		
		allTextures[GameConVars.GRAPHIC_PROJECTILES[0]] = loadTexture(gl, Bitmap.createBitmap(mSpriteSheet, 384, 1152, 128, 128), 128, 128);
		
		allTextures[GameConVars.GRAPHIC_BASES[0]] = loadTexture(gl, Bitmap.createBitmap(mSpriteSheet, 0, 1536, 512, 128), 512, 128);
		
		mSpriteSheet.recycle();
		mSpriteSheet = null;
	}
	
	public void loadUITextures(GL10 gl){
		options = new BitmapFactory.Options();
		options.inPurgeable = true;
		
    	long time = System.nanoTime();
	
		if(mUISheet == null){
			mUISheet = BitmapFactory.decodeResource(mContext.getResources(), R.drawable.uisheet, options);
		}
		
		allTextures[GameConVars.UI_SPINNER]   	= loadTexture(gl, Bitmap.createBitmap(mUISheet, 1024, 0, 1024, 128), 128, 128);
		allTextures[GameConVars.AIM]       		= loadTexture(gl, Bitmap.createBitmap(mUISheet, 768, 128, 128, 128), 128, 128);
		allTextures[GameConVars.MENUBACKGROUND] = loadTexture(gl, Bitmap.createBitmap(mUISheet, 0, 512, 512, 512), 512, 512);
		allTextures[GameConVars.BUTTON]         = loadTexture(gl, Bitmap.createBitmap(mUISheet, 512, 640, 512, 32), 128, 32);
		allTextures[GameConVars.ARROW]          = loadTexture(gl, Bitmap.createBitmap(mUISheet, 512, 0, 128, 128), 128, 128);
		allTextures[GameConVars.SELECTION]      = loadTexture(gl, Bitmap.createBitmap(mUISheet, 1536, 1536, 128, 128), 128, 128);
		allTextures[GameConVars.ENDTURN]        = loadTexture(gl, Bitmap.createBitmap(mUISheet, 640, 128, 128, 128), 128, 128);
		allTextures[GameConVars.SHOOT]          = loadTexture(gl, Bitmap.createBitmap(mUISheet, 512, 128, 128, 128), 128, 128);
		allTextures[GameConVars.TURNAROUND]     = loadTexture(gl, Bitmap.createBitmap(mUISheet, 512, 256, 128, 128), 128, 128);
		allTextures[GameConVars.GO]             = loadTexture(gl, Bitmap.createBitmap(mUISheet, 640, 256, 128, 128), 128, 128);
		allTextures[GameConVars.CAPTURE_RESOURCE]       = loadTexture(gl, Bitmap.createBitmap(mUISheet, 768, 0, 128, 128), 128, 128);
		allTextures[GameConVars.OFFLINE_MAP_BUTTON]     = loadTexture(gl, Bitmap.createBitmap(mUISheet, 640, 384, 128, 128), 128, 128);
		allTextures[GameConVars.ONLINE_MAP_BUTTON]      = loadTexture(gl, Bitmap.createBitmap(mUISheet, 512, 384, 128, 128), 128, 128);
		allTextures[GameConVars.GRAPHIC_WIND]           = loadTexture(gl, Bitmap.createBitmap(mUISheet, 512, 512, 256, 64), 256, 64);
		allTextures[GameConVars.GRAPHIC_BUTTON_BORDER]  = loadTexture(gl, Bitmap.createBitmap(mUISheet, 512, 768,512, 512), 128, 128);
		allTextures[GameConVars.GRAPHIC_WINDOW_BORDER]  = loadTexture(gl, Bitmap.createBitmap(mUISheet, 0, 1024,512, 512), 512, 512);
		allTextures[GameConVars.GRAPHIC_LOADINGSCREEN]  = loadTexture(gl, Bitmap.createBitmap(mUISheet, 0, 1536,512, 512), 512, 512);
		
		// Tech Menu Buttons
		// TODO Uncomment and fix locations / Bitmap Sheet when we have unique images for the Tech buttons.
		// ECONOMIC
		allTextures[GameConVars.GRAPHIC_TECHTREE_ECONOMIC[0]]      = loadTexture(gl, Bitmap.createBitmap(mUISheet, 896, 0, 128, 128), 128, 128);
		allTextures[GameConVars.GRAPHIC_TECHTREE_ECONOMIC[1]]      = loadTexture(gl, Bitmap.createBitmap(mUISheet, 896, 0, 128, 128), 128, 128);
		allTextures[GameConVars.GRAPHIC_TECHTREE_ECONOMIC[2]]      = loadTexture(gl, Bitmap.createBitmap(mUISheet, 896, 0, 128, 128), 128, 128);
		allTextures[GameConVars.GRAPHIC_TECHTREE_ECONOMIC[3]]      = loadTexture(gl, Bitmap.createBitmap(mUISheet, 896, 0, 128, 128), 128, 128);
		allTextures[GameConVars.GRAPHIC_TECHTREE_ECONOMIC[4]]      = loadTexture(gl, Bitmap.createBitmap(mUISheet, 896, 0, 128, 128), 128, 128);
		allTextures[GameConVars.GRAPHIC_TECHTREE_ECONOMIC[5]]      = loadTexture(gl, Bitmap.createBitmap(mUISheet, 896, 0, 128, 128), 128, 128);
		// TACTICAL
		allTextures[GameConVars.GRAPHIC_TECHTREE_TACTICAL[0]]      = loadTexture(gl, Bitmap.createBitmap(mUISheet, 896, 0, 128, 128), 128, 128);
		allTextures[GameConVars.GRAPHIC_TECHTREE_TACTICAL[1]]      = loadTexture(gl, Bitmap.createBitmap(mUISheet, 896, 0, 128, 128), 128, 128);
		allTextures[GameConVars.GRAPHIC_TECHTREE_TACTICAL[2]]      = loadTexture(gl, Bitmap.createBitmap(mUISheet, 896, 0, 128, 128), 128, 128);
		allTextures[GameConVars.GRAPHIC_TECHTREE_TACTICAL[3]]      = loadTexture(gl, Bitmap.createBitmap(mUISheet, 896, 0, 128, 128), 128, 128);
		allTextures[GameConVars.GRAPHIC_TECHTREE_TACTICAL[4]]      = loadTexture(gl, Bitmap.createBitmap(mUISheet, 896, 0, 128, 128), 128, 128);
		allTextures[GameConVars.GRAPHIC_TECHTREE_TACTICAL[5]]      = loadTexture(gl, Bitmap.createBitmap(mUISheet, 896, 0, 128, 128), 128, 128);
		// DESTRUCTIVE
		allTextures[GameConVars.GRAPHIC_TECHTREE_DESTRUCTIVE[0]]   = loadTexture(gl, Bitmap.createBitmap(mUISheet, 896, 0, 128, 128), 128, 128);
		allTextures[GameConVars.GRAPHIC_TECHTREE_DESTRUCTIVE[1]]   = loadTexture(gl, Bitmap.createBitmap(mUISheet, 896, 0, 128, 128), 128, 128);
		allTextures[GameConVars.GRAPHIC_TECHTREE_DESTRUCTIVE[2]]   = loadTexture(gl, Bitmap.createBitmap(mUISheet, 896, 0, 128, 128), 128, 128);
		allTextures[GameConVars.GRAPHIC_TECHTREE_DESTRUCTIVE[3]]   = loadTexture(gl, Bitmap.createBitmap(mUISheet, 896, 0, 128, 128), 128, 128);
		allTextures[GameConVars.GRAPHIC_TECHTREE_DESTRUCTIVE[4]]   = loadTexture(gl, Bitmap.createBitmap(mUISheet, 896, 0, 128, 128), 128, 128);
		allTextures[GameConVars.GRAPHIC_TECHTREE_DESTRUCTIVE[5]]   = loadTexture(gl, Bitmap.createBitmap(mUISheet, 896, 0, 128, 128), 128, 128);
		
		mFontBitmap = Bitmap.createBitmap(mUISheet, 0, 0, 512, 512);
		
		mUISheet.recycle();
		mUISheet = null;
		
		long elapse = System.nanoTime() - time;
		Logger.log("loading ui took: " + elapse/1000000);

		new Thread(new Runnable() {
			public void run() {
				LoadingScreen.getInstance().init();
			}
		}).start();
	}

	public void loadBackgroundTextures(GL10 gl){
		if(mBackgroundSheet == null){
			mBackgroundSheet = BitmapFactory.decodeResource(mContext.getResources(), R.drawable.backgroundsheet, options);
		}
		
		allTextures[GameConVars.GRAPHIC_BACKGROUND1] = loadTexture(gl, Bitmap.createBitmap(mBackgroundSheet, 0, 1536, 2048, 512), 512, 512);
		allTextures[GameConVars.GRAPHIC_FOREGROUND1] = loadTexture(gl, Bitmap.createBitmap(mBackgroundSheet, 0, 0, 512, 512), 512, 512);
		allTextures[GameConVars.GRAPHIC_BACKGROUND2] = loadTexture(gl, Bitmap.createBitmap(mBackgroundSheet, 512, 512, 512, 512), 512, 512);
		allTextures[GameConVars.GRAPHIC_FOREGROUND2] = loadTexture(gl, Bitmap.createBitmap(mBackgroundSheet, 0, 512, 512, 512), 512, 512);
		allTextures[GameConVars.GRAPHIC_BACKGROUND3] = loadTexture(gl, Bitmap.createBitmap(mBackgroundSheet, 512, 1024, 512, 512), 512, 512);
		allTextures[GameConVars.GRAPHIC_FOREGROUND3] = loadTexture(gl, Bitmap.createBitmap(mBackgroundSheet, 0, 1024, 512, 512), 512, 512);
		
		mBackgroundSheet.recycle();
		mBackgroundSheet = null;
	}
	
	private int[] loadTexture(GL10 gl, Bitmap bitmap, int frameWidth, int frameHeight){
		int frames = bitmap.getWidth() / frameWidth;
		int[] textures = new int[frames];
		// Generate Texture Pointer
		gl.glGenTextures(frames, textures, 0);
		for(int i = 0; i < frames; i++){
			Bitmap currentFrame = frames == 1 ? bitmap : Bitmap.createBitmap(bitmap, i*frameWidth, 0, frameWidth, frameHeight);
			// Bind to Array
			gl.glBindTexture(GL10.GL_TEXTURE_2D, textures[i]);
			// Create Filtered Texture													NEAREST = Crisp  LINEAR = Blurred
			gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_NEAREST);
			gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_NEAREST);
			// Specify Image for Bitmap
			GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, currentFrame, 0);
			currentFrame.recycle();
		}
		return textures;
	}
	
	public Bitmap getFontBitmap(){
		return mFontBitmap;
	}
}
